#!/usr/bin/perl
#use strict;

## Source :: GSA Developer's protocol :: https://developers.google.com/search-appliance/documentation/614/gdata/acapi_protocol
## This API structure reduces debugging visibility and is only for expert ADMINS.

use LWP::UserAgent;
use XML::Simple;
use Getopt::Long; ## http://perldoc.perl.org/Getopt/Long.html

my ($appliance, $api, $action, $collection, $date);
GetOptions ("appliance=s"   => \$appliance,     ## GSA Name
            "api=s"         => \$api,           ## API Name
            "action=s"      => \$action,        ## Function to perform on that API
            "collection=s"  => \$collection,    ## Name of the collection
            "date=s"        => \$date,          ## date for which the action needs to be performed
            ) 
or die("Error in command line arguments\n");

## Validate API, Function call and argument validations
if (!(-d "./plugins/$api")) {
    print "Unable to identify the API \"$api\"\n";
    exit;
}

if (!(-f "./plugins/$api/$action")) {
    print "Unable to identify the function \"$action\" you are trying to perform for API \"$api\" \n";
    exit;
}

if (-f "./plugins/$api/validate") {
    ## Read perl code file
    open(FILE, "<./plugins/$api/validate") or die "cannot open file \"/plugins/$api/validate\" for reason $!";
        my @string = <FILE>;
    close FILE;
    my $string = join "", @string;
    eval ($string);
}

## Set Master user agent and populate authentication headers ##
my  $res;
my  $ua = LWP::UserAgent->new;
    $ua->agent("GSA-Admin-Toolkit/0.1");
    $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
    
## Connect with GSA
my  $appliance_id   = "$appliance";
my  $auth_token;
    ($appliance_id, $auth_token)         = &authenticate($appliance_id);
    $ua->default_header( "Authorization" => "GoogleLogin auth=$auth_token");

## Standard API processing block
my ($status, $data, @output);

## API defaults can be coded here
if ($action eq 'default'){
    ## Read perl code file
    open(FILE, "<./plugins/$api/default") or die "cannot open file \"/plugins/$api/default\" for reason $!";
        my @string = <FILE>;
    close FILE;
    
    my $string = join "", @string;
    my @output = eval ($string);
    
    if ($@) {
        print "Error Caught while parsing response for $api \n\t". $@ ."\n\n";
    }else{
        print @output;
    }
}else{
    ## This should be else block for independent functions
    ($status, $data) = &get($appliance_id, $api, $action, $collection, $date);
    @output          = &response($status,$data, $api);
    print join "\n", @output;
}

## Reset headers and exit
$ua->delete;

print "Please press any key to continue .."; <>;
exit;

## Use this function to submit request to GSA
sub get(){
    my $hostname        = $_[0];
    my $api             = $_[1];
    my $action          = $_[2];
    my $collection      = $_[3];
    my $date            = $_[4];

    ## Read perl code file
    open(FILE, "<./plugins/$api/$action") or die "cannot open file \"/plugins/$api/$action\" for reason $!";
        my @string = <FILE>;
    close FILE;
    
    ## Initialized variables
    my ($request_type, $url, $content);
    my $string = join "", @string;
    my @output = eval ($string);
    
    if ($@) {
        print "Error Caught while parsing request for $api \n\t". $@ ."\n\n";
    }
    
    $url = "$hostname/$url";
    
    # Pass request to the user agent and get a response back
    my  $req = HTTP::Request->new($request_type => "$url");
        $req->content_type('application/atom+xml');
        $req->content($content);
        $res = $ua->request($req);
        
    if ($res->is_success) {
        return 'SUCCESS',   $res->content;
    }else{
        return 'ERROR',     $res->content;
    } 
}

## Use this function to parse reponses
sub response(){
    my $report_type = $_[0]; ## success / error
    my $source      = $_[1]; ## data to parse
    my $api         = $_[2]; ## Function to chose from plugins folder
    my $xml         = new XML::Simple;
    my $data        = $xml->XMLin($source);

    ## Read perl code file
    open(FILE, "<./plugins/$api/response") or die "cannot open file \"/plugins/$api/response\" for reason $!";
        my @string = <FILE>;
    close FILE;

    my $string = join "", @string;
    my @output = eval ($string);
    
    if ($@) {
        print "Error Caught while parsing response for $api \n\t". $@ ."\n\n";
    }else{
        return @output;
    }
}

## Use this function to get authentication token
sub authenticate($){
    my $appliance_id = $_[0];
    
    ## Read perl code file
    open(FILE, "<./gsa/$appliance_id") or die "cannot open file \"./gsa/$appliance_id\" for reason $!";
        my @string = <FILE>;
    close FILE;
    
    my ($protocol, $port, $FQDN, $username, $password);
    
    my $string = join "", @string;
    eval ($string);
    
    my $appliance_url   = "$protocol://$appliance_id.$FQDN:$port";
    my $action_url      = "$appliance_url/accounts/ClientLogin";
    # Create a request
    my  $req = HTTP::Request->new(POST => $action_url);
        ## Post headers
        $req->content_type('application/x-www-form-urlencoded');
        $req->content("&Email=$username&Passwd=$password");
    
    # Pass request to the user agent and get a response back
    $res = $ua->request($req);
    
    # Check the outcome of the response
    if ($res->is_success) {
        my $auth = $res->content;
        my  @auth_token  = split "\n", $auth;
            @auth_token  = split"=", $auth_token[1];
            $auth_token = $auth_token[1];
        return ($appliance_url, $auth_token);
    }else {
        print $res->status_line, "\n";
        die;
    }
}